/**
 * 
 */
package org.t2.game.server.module.rank;

import org.gaming.fakecmd.annotation.InternalCmd;
import org.gaming.fakecmd.annotation.PlayerCmd;
import org.gaming.service.asserts.Asserts;
import org.gaming.tool.DateTimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.t2.game.server.foundation.player.PlayerContext;
import org.t2.game.server.module.player.message.PlayerForbidRankMessage;
import org.t2.game.server.module.player.model.Player;
import org.t2.game.server.module.player.service.PlayerService;
import org.t2.game.server.module.rank.constant.RankType;
import org.t2.game.server.module.rank.model.Ranker;
import org.t2.game.server.module.rank.service.RankerContext;
import org.t2.game.server.module.rank.service.RankerService;
import org.t2.game.server.module.tips.TipsCode;

import pb.t2.protobuf.rank.Rank.PbRankGroup;
import pb.t2.protobuf.rank.Rank.PbRanker;
import pb.t2.protobuf.rank.Rank.RankAddRequest;
import pb.t2.protobuf.rank.Rank.RankAddResponse;
import pb.t2.protobuf.rank.Rank.RankInfoRequest;
import pb.t2.protobuf.rank.Rank.RankInfoResponse;

/**
 * 
 */
@Controller
public class RankHandler {

	@Autowired
	private RankerService rankerService;
	@Autowired
	private PlayerService playerService;
	
	@PlayerCmd
	public RankInfoResponse info(PlayerContext playerContext, RankInfoRequest request) {
		RankInfoResponse.Builder response = RankInfoResponse.newBuilder();
		
		for(RankType rankType : RankType.values()) {
			if(rankType == RankType.RECHARGE) {
				continue;
			}
			RankerContext context = rankerService.getContext(rankType);
			response.addRankGroups(build(playerContext.getId(), context));
		}
		return response.build();
	}
	
	public PbRankGroup build(long playerId, RankerContext context) {
		PbRankGroup.Builder builder = PbRankGroup.newBuilder();
		
		int startIndex = 1;
		int endIndex = 50;
		
		builder.setRankType(context.getRankType().getValue());
		builder.setRankPage(1);
		int rank = startIndex;
		for(Ranker ranker : context.getTopN(startIndex, endIndex)) {
			builder.addRankers(build(ranker, rank));
			rank += 1;
		}
		Ranker myRanker = context.getRanker(playerId);
		int myRank = 0;
		if(myRanker == null) {
			myRanker = new Ranker();
			myRanker.setPlayerId(playerId);
			myRanker.setType(context.getRankType().getValue());
			myRanker.setExtraData("");
		} else {
			myRank = context.getRank(myRanker);
		}
		builder.setMyRanker(build(myRanker, myRank));
		
		return builder.build();
	}	
	
	public PbRanker build(Ranker ranker, int rank) {
		Player player = playerService.getEntity(ranker.getPlayerId());
		
		PbRanker.Builder builder = PbRanker.newBuilder();
		builder.setRank(rank);
		builder.setPlayerId(ranker.getPlayerId());
		builder.setScore(ranker.getScore());
		builder.setSubScore(ranker.getSubScore());
		builder.setExtraData(ranker.getExtraData());
		builder.setNick(player.getNick());
		builder.setHead(player.getHead());
		return builder.build();
	}
	
	@PlayerCmd
	public RankAddResponse addRank(PlayerContext playerContext, RankAddRequest request) {
		RankType rankType = RankType.valueOf(request.getRankType());
		Asserts.isTrue(rankType != null && rankType != RankType.RECHARGE, TipsCode.RANK_TYPE_ERROR);
		
		Player player = playerService.getEntity(playerContext.getId());
		if(player.getForbidRankTime() > DateTimeUtil.currMillis()) {
			return RankAddResponse.getDefaultInstance();
		}
		
		RankerContext context = rankerService.getContext(rankType);
		context.updateRank(playerContext.getId(), request.getScore(), request.getSubScore(), request.getExtraData());
		
		return RankAddResponse.getDefaultInstance();
	}
	
	@InternalCmd
    public void forbidRank(PlayerForbidRankMessage message) {
        Player player = playerService.getEntity(message.getPlayerId());
        player.setForbidRankTime(message.getForbidEndTime());
        playerService.update(player);
        playerService.addToReport(player);
        
        rankerService.cleanInRank(player.getId());
    }
}
